package com.usefullc.blog.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.usefullc.common.exception.BizException;
import com.usefullc.common.util.BeanUtils;
import com.usefullc.blog.domain.Category;
import com.usefullc.blog.mapper.CategoryMapper;
import com.usefullc.blog.query.CategoryQuery;
import com.usefullc.blog.vo.CategoryVo;
import com.usefullc.system.entity.Pager;
import com.usefullc.system.service.AbstractBizService;
import com.usefullc.system.service.SerialNumberService;
import com.usefullc.system.vo.TreeVo;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * 类目服务类
 * @author: 星空
 * @date: 20220628
 */
@Service
public class CategoryService extends AbstractBizService<CategoryMapper, Category, CategoryQuery> {

    @Autowired
    private SerialNumberService serialNumberService;

    @Override
    protected QueryWrapper<Category> getQueryWrapper(CategoryQuery query) {
        QueryWrapper<Category> queryWrapper = super.getQueryWrapper(query);

//        queryWrapper.apply(StringUtils.isNotBlank(query.getGmtCreateStart()),
//                "date_format (gmtCreate,'%Y-%m-%d') >= date_format('" + query.getGmtCreateStart() + "','%Y-%m-%d')")
//                .apply(StringUtils.isNotBlank(query.getGmtCreateEnd()),
//                        "date_format (gmtCreate,'%Y-%m-%d') <= date_format('" + query.getGmtCreateEnd() + "','%Y-%m-%d')");

        return queryWrapper;
    }


    public List<Category> getChildrenByCodeLike(String codeLike) {
        CategoryQuery query = new CategoryQuery();
        query.setOrderByColumn("orderNo");
        query.setAscOrDesc("asc");
        query.setCodeLike(codeLike);
        return this.findAll(query);
    }

    public List<Category> getChildrenByParentId(Long parentId) {
        CategoryQuery query = new CategoryQuery();
        query.setOrderByColumn("orderNo");
        query.setAscOrDesc("asc");
        query.setParentId(parentId);
        return this.findAll(query);
    }


    public Pager<CategoryVo> findVoByPage(CategoryQuery query) {
        query.setParentId(0L);
        query.setOrderByColumn("orderNo");
        query.setAscOrDesc("asc");
        Pager<Category> pager = this.findByPage(query);
        List<Category> dataList = pager.getDataList();
        Pager<CategoryVo> newPager = new Pager<>(pager);
        List<CategoryVo> newDataList = new ArrayList<>();
        newPager.setDataList(newDataList);
        if (CollectionUtils.isNotEmpty(dataList)) {
            for (Category category : dataList) {
//                categoryVo.setChildren(Lists.newArrayList());
                CategoryVo categoryVo = BeanUtils.beanCopy(category, CategoryVo.class);
                newDataList.add(categoryVo);

                //

                List<CategoryVo> children = new ArrayList<>();
                //获取子集
                List<Category> childDataList = getChildrenByCodeLike(category.getCode());

                setChildren(childDataList,children,categoryVo);

            }
        }
        return newPager;
    }

    private void setChildren(List<Category> childDataList, List<CategoryVo> children, CategoryVo categoryVo){
        for (Category category : childDataList) {
            if (category.getParentId() != categoryVo.getId().longValue()) {
                continue;
            }
            CategoryVo childCategoryVo = BeanUtils.beanCopy(category, CategoryVo.class);
            children.add(childCategoryVo);
            List<CategoryVo> subChildren = new ArrayList<>();
            setChildren(childDataList,subChildren,childCategoryVo);
        }
        if(children.size() > 0){
            categoryVo.setChildren(children);
        }
    }

    public List<TreeVo> listTree(CategoryQuery query){
        query.setParentId(0L);
        List<Category> dataList = this.findAll(query);
        List<TreeVo> newDataList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(dataList)) {
            for (Category category : dataList) {
                TreeVo treeVo = new TreeVo();
                newDataList.add(treeVo);
                treeVo.setTitle(category.getName());
                treeVo.setValue(category.getId().toString());
                treeVo.setKey(category.getId().toString());
                treeVo.setUrl(category.getUrl());
                List<TreeVo> children = new ArrayList<>();
                //获取子集
                List<Category> childDataList = getChildrenByCodeLike(category.getCode());

                setTreeChildren(childDataList,children,treeVo);
            }
        }
        //添加根目录
//        TreeVo treeVo = new TreeVo();
//        treeVo.setTitle("根目录");
//        treeVo.setValue("0");
//        treeVo.setKey("0");
//        newDataList.add(0,treeVo);
        return newDataList;
    }

    private void setTreeChildren(List<Category> childDataList, List<TreeVo> children, TreeVo treeVo){
        for (Category childCategory : childDataList) {
            if (childCategory.getParentId() != Long.valueOf(treeVo.getValue()).longValue()) {
                continue;
            }
            TreeVo childTreeVo = new TreeVo();
            childTreeVo.setTitle(childCategory.getName());
            childTreeVo.setValue(childCategory.getId().toString());
            childTreeVo.setKey(childCategory.getId().toString());
            childTreeVo.setUrl(childCategory.getUrl());
            children.add(childTreeVo);

            List<TreeVo> subChildren = new ArrayList<>();
            setTreeChildren(childDataList,subChildren,childTreeVo);
        }
        if(children.size() > 0){
            treeVo.setChildren(children);
        }
    }

    @Override
    public boolean save(Category entity) {
        super.save(entity);
        return this.update(entity);
    }

    @Override
    public boolean update(Category entity) {
        //设置路径
        entity.setUrl("/cmsBlog/category/"+entity.getId()+".html");
        return super.update(entity);
    }

    public Category saveCategory(Category category) {
        Long parentId = category.getParentId();
        if (parentId == null) {
            parentId = 0L;
        }
        String parentCode = "0";
        if(parentId != 0){
            parentCode = this.findById(parentId).getCode();
        }
        category.setParentId(parentId);
        String no = serialNumberService.getSerialNumber("blog_category", parentCode);
        category.setCode(no);
        this.save(category);


        this.update(category);
        return category;
    }

    public Category updateCategory(Category category){
        Long parentId = category.getParentId();
        if (parentId == null) {
            parentId = 0L;
        }
        if(parentId.longValue() == category.getId()){
            throw new BizException("不能作为自己的父级",false);
        }
        Category oldBean = this.findById(category.getId());
        Long oldParentId = oldBean.getParentId();
        BeanUtils.beanCopy(category,oldBean);
        if(oldParentId == parentId.longValue()){  //直接修改属性
            this.update(oldBean);
        }else{  //修改了父级，则涉及到的编码包括该级的下一级编码都得改
            String parentCode = "0";
            if(parentId != 0){
                parentCode = this.findById(parentId).getCode();
            }
            String no = serialNumberService.getSerialNumber("blog_category", parentCode);
            oldBean.setCode(no);
            this.update(oldBean);

            //查询下一级修改
            updateChildrenForNo(oldBean.getId(),no);
        }
        return oldBean;
    }

    private void updateChildrenForNo(Long parentId,String parentNo){
        List<Category> childCategoryList = this.getChildrenByParentId(parentId);
        if(CollectionUtils.isNotEmpty(childCategoryList)){
            for (Category childCategory : childCategoryList) {
                String childNo = serialNumberService.getSerialNumber("blog_category", parentNo);
                childCategory.setCode(childNo);
                this.save(childCategory);

                updateChildrenForNo(childCategory.getId(),childNo);

            }
        }
    }

}
